package br.com.me.ceap;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.installer.ArtifactInstaller;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.WriterFactory;

import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;

/**
 * Created by Bruno Mendonça with IntelliJ IDEA.
 * User: brunol
 * Date: 14/10/11
 * Time: 12:41
 */
public abstract class BaseMojo extends AbstractMojo {
// ------------------------------ FIELDS ------------------------------

    /**
     * Directory the project.
     *
     * @parameter default-value="${basedir}"
     * @required
     */
    protected File projectBaseDir;

    /**
     * @component
     */
    protected ArtifactFactory artifactFactory;
    /**
     * Classifier type of the artifact to be installed. For example, "sources" or "javadoc". Defaults to none which
     * means this is the project's main artifact.
     *
     * @parameter expression="${classifier}"
     * @readonly
     */
    protected String classifier;
    /**
     * @component
     */
    protected ArtifactInstaller installer;
    /**
     * @parameter expression="${localRepository}"
     * @required
     * @readonly
     */
    protected ArtifactRepository localRepository;


    /**
     * ME CEAP Username.
     *
     * @parameter
     * @required
     */
    private String username;
    /**
     * ME CEAP Password.
     *
     * @parameter
     * @required
     */
    private String password;
    /**
     * ME CEAP URL.
     *
     * @parameter
     * @required
     */
    private String url;
    /**
     * ME CEAP Custom Root Id.
     *
     * @parameter
     * @required
     */
    private String customRootName;
    /**
     * Proxy Server (optional).
     *
     * @parameter
     */
    private String proxy_server;
    /**
     * Proxy Port (optional).
     *
     * @parameter
     */
    private int proxy_port;
    /**
     * Proxy Username (optional).
     *
     * @parameter
     */
    private String proxy_username;
    /**
     * Proxy Password (optional).
     *
     * @parameter
     */
    private String proxy_password;
    /**
     * ME CEAP Custom Root JAR version.
     *
     * @parameter
     * @required
     */
    protected String version;

// --------------------- GETTER / SETTER METHODS ---------------------

    public String getCustomRootName() {
        return customRootName;
    }

    public void setCustomRootName(String customRootName) {
        this.customRootName = customRootName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getProxy_password() {
        return proxy_password;
    }

    public void setProxy_password(String proxy_password) {
        this.proxy_password = proxy_password;
    }

    public int getProxy_port() {
        return proxy_port;
    }

    public void setProxy_port(int proxy_port) {
        this.proxy_port = proxy_port;
    }

    public String getProxy_server() {
        return proxy_server;
    }

    public void setProxy_server(String proxy_server) {
        this.proxy_server = proxy_server;
    }

    public String getProxy_username() {
        return proxy_username;
    }

    public void setProxy_username(String proxy_username) {
        this.proxy_username = proxy_username;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

// -------------------------- OTHER METHODS --------------------------

    protected JarBundler bundleFilesInJAR(final String typeFile, final String subDirName, final File filesDirectory, final IOFileFilter filter, boolean recursiveSearch) throws MojoFailureException {
        this.getLog().info(String.format("Preparing to upload %s files.", typeFile));

        this.getLog().info(String.format("Looking for %s files in %s", typeFile, filesDirectory.getPath()));
        if (!filesDirectory.exists()) {
            throw new MojoFailureException(String.format("%s files directory %s does not exist.", typeFile, subDirName));
        }

        JarBundler jarBundler = new JarBundler();

        Collection<File> foundFiles = FileUtils.listFiles(filesDirectory, filter, recursiveSearch ? TrueFileFilter.INSTANCE : null);

        if (foundFiles.size() == 0) {
            throw new MojoFailureException(String.format("No %s files found.", typeFile));
        }

        for (File mappingFile : foundFiles) {
            String absolutePath = mappingFile.getAbsolutePath();
            if (absolutePath.contains(".svn")) continue;
            this.getLog().info(String.format("Adding %s file %s to upload list...", typeFile, absolutePath));
            jarBundler.addEntry(mappingFile);
        }
        return jarBundler;
    }

    protected File generatePomFile(String groupId, String version, String packaging) throws MojoExecutionException {
        Model model = new Model();
        model.setModelVersion("4.0.0");
        model.setGroupId(groupId);
        model.setArtifactId(this.getCustomRootName());
        model.setVersion(version);
        model.setPackaging(packaging);
        model.setDescription("POM was created by MECEAP plugin");

        Writer writer = null;
        try {
            this.getLog().debug("Creating pom temp file");
            File pomFile = File.createTempFile("ceap-plugin", ".pom");

            writer = WriterFactory.newXmlWriter(pomFile);
            new MavenXpp3Writer().write(writer, model);

            return pomFile;
        } catch (IOException e) {
            throw new MojoExecutionException("Error writing temporary POM file: " + e.getMessage(), e);
        } finally {
            IOUtil.close(writer);
        }
    }

    protected void uploadFileToWebClient(final WebClient webClient, final byte[] jarFile, String description) throws MojoExecutionException {
        ContentDisposition cd = new ContentDisposition("attachment;filename=jarFile.jar");
        Attachment att = new Attachment("jarFile", new ByteArrayInputStream(jarFile), cd);
        Response response = webClient.post(new MultipartBody(att));

        if (response.getStatus() == 204) {
            this.getLog().info(String.format("%s successfully deployed", description));
            return;
        }

        // Try to show off comprehensive info on console
        this.getLog().error(String.format("Error on deploying %s: Status = %d", description, response.getStatus()));
        try {
            this.getLog().error(MECEAPUtils.getResponseBody(response));
        } catch (IOException e) {
            this.getLog().error("No further message received from server");
        }

        throw new MojoExecutionException(String.format("Failed to deploy %s", description));
    }
}
